﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using YJKArchMethodLibrary.Utils;

namespace Aproll.DataDefine
{
	public class BaseLineSegmentLinkedGraph
	{
		public BaseLineSegmentLinkedGraph()
		{
		}

		public BaseLineSegmentLinkedGraph(BaseLineSegmentLinkedGraph other)
		{
			this.m_LinkedGraph = other.m_LinkedGraph;
		}

		public bool BaseLineSegmentLinkedGroup(ref List<List<BaseLineSegment>> groups)
		{
			List<BaseLineNode> allNodes = this.GetAllNodes();
			while (allNodes.Count > 0)
			{
				BaseLineNode leftBottomNode = this.GetLeftBottomNode(allNodes);
				BaseLineSegment baseLineSegment = leftBottomNode.SegmentList[0];
				List<BaseLineSegment> collection = new List<BaseLineSegment>();
				List<BaseLineSegment> collection2 = new List<BaseLineSegment>();
				List<BaseLineNode> list = new List<BaseLineNode>();
				if (!this.GetLinkedBaseLineSegments(baseLineSegment, ref collection, ref collection2, ref list))
				{
					return false;
				}
				List<BaseLineSegment> list2 = new List<BaseLineSegment>();
				list2.AddRange(collection);
				list2.Add(baseLineSegment);
				list2.AddRange(collection2);
				groups.Add(list2);
				foreach (BaseLineNode item in list)
				{
					allNodes.Remove(item);
				}
			}
			return true;
		}

		public void Clear()
		{
			this.m_LinkedGraph.Clear();
		}

		public void ChangeBaseLineSegmentOrientation(BaseLineSegment segment)
		{
			List<BaseLineSegment> list = new List<BaseLineSegment>();
			List<BaseLineSegment> collection = new List<BaseLineSegment>();
			List<BaseLineNode> list2 = new List<BaseLineNode>();
			if (!this.GetLinkedBaseLineSegments(segment, ref list, ref collection, ref list2))
			{
				segment.Segment.ReverseSelf();
				return;
			}
			list.Add(segment);
			list.AddRange(collection);
			foreach (BaseLineSegment baseLineSegment in list)
			{
				baseLineSegment.Segment.ReverseSelf();
			}
		}

		public bool AddBaseLineSegment(BaseLineSegment segment, ref string message)
		{
			if (this.IsOverLap(segment))
			{
				message = "线段重叠";
				return false;
			}
			if (Geometry.LessThan(segment.Segment.Length(), Common.MMToFeet(0.8)))
			{
				message = "线段长度太短";
				return false;
			}
			XYZ xyz = segment.Segment.StartPoint;
			if (!this.m_LinkedGraph.ContainsKey(xyz))
			{
				BaseLineNode value = new BaseLineNode(xyz, new List<BaseLineSegment>
				{
					segment
				});
				this.m_LinkedGraph.Add(xyz, value);
			}
			else
			{
				BaseLineNode baseLineNode = this.m_LinkedGraph[xyz];
				if (baseLineNode.SegmentList.Count > 1)
				{
					message = "边线不能出现分支";
					return false;
				}
				baseLineNode.AddSegment(segment);
			}
			xyz = segment.Segment.EndPoint;
			if (!this.m_LinkedGraph.ContainsKey(xyz))
			{
				BaseLineNode value2 = new BaseLineNode(xyz, new List<BaseLineSegment>
				{
					segment
				});
				this.m_LinkedGraph.Add(xyz, value2);
			}
			else
			{
				BaseLineNode baseLineNode2 = this.m_LinkedGraph[xyz];
				if (baseLineNode2.SegmentList.Count > 1)
				{
					message = "边线不能出现分支";
					return false;
				}
				baseLineNode2.AddSegment(segment);
			}
			this.AutoSyncLinkedSegmentsOrientation(segment);
			return true;
		}

		public bool RemoveBaseLineSegment(BaseLineSegment segment)
		{
			bool result = false;
			XYZ key = segment.Segment.StartPoint;
			if (this.m_LinkedGraph.ContainsKey(key))
			{
				BaseLineNode baseLineNode = this.m_LinkedGraph[key];
				baseLineNode.RemoveSegment(segment);
				result = true;
				if (baseLineNode.SegmentList.Count == 0)
				{
					this.m_LinkedGraph.Remove(key);
				}
			}
			key = segment.Segment.EndPoint;
			if (this.m_LinkedGraph.ContainsKey(key))
			{
				BaseLineNode baseLineNode2 = this.m_LinkedGraph[key];
				baseLineNode2.RemoveSegment(segment);
				result = true;
				if (baseLineNode2.SegmentList.Count == 0)
				{
					this.m_LinkedGraph.Remove(key);
				}
			}
			return result;
		}

		public bool FindBaseLineSegment(EdgeInfo edgeInfo, ref BaseLineSegment findedSegment)
		{
			List<BaseLineSegment> baseLineSegments = this.GetBaseLineSegments();
			foreach (BaseLineSegment baseLineSegment in baseLineSegments)
			{
				if (baseLineSegment.IsEqual(edgeInfo))
				{
					findedSegment = baseLineSegment;
					return true;
				}
			}
			return false;
		}

		public bool IsOverLap(BaseLineSegment testSegment)
		{
			List<BaseLineSegment> baseLineSegments = this.GetBaseLineSegments();
			foreach (BaseLineSegment other in baseLineSegments)
			{
				if (testSegment.IsOverlap(other))
				{
					return true;
				}
			}
			return false;
		}

		public List<BaseLineSegment> GetBaseLineSegments()
		{
			List<BaseLineSegment> list = new List<BaseLineSegment>();
			foreach (KeyValuePair<XYZ, BaseLineNode> keyValuePair in this.m_LinkedGraph)
			{
				using (List<BaseLineSegment>.Enumerator enumerator2 = keyValuePair.Value.SegmentList.GetEnumerator())
				{
					while (enumerator2.MoveNext())
					{
						BaseLineSegment segment = enumerator2.Current;
						int num = list.FindIndex((BaseLineSegment value) => value.IsEqual(segment));
						if (-1 == num)
						{
							list.Add(segment);
						}
					}
				}
			}
			return list;
		}

		private void AutoSyncLinkedSegmentsOrientation(BaseLineSegment newSegment)
		{
			List<BaseLineSegment> list = new List<BaseLineSegment>();
			List<BaseLineSegment> list2 = new List<BaseLineSegment>();
			List<BaseLineNode> list3 = new List<BaseLineNode>();
			this.GetLinkedBaseLineSegments(newSegment, ref list, ref list2, ref list3);
			bool flag = false;
			bool flag2 = false;
			if (list.Count > 0)
			{
				XYZ endPoint = list[list.Count - 1].Segment.EndPoint;
				if (Geometry.IsEqual(endPoint, newSegment.Segment.StartPoint, 0.0001))
				{
					flag = true;
				}
			}
			else
			{
				flag = true;
			}
			if (list2.Count > 0)
			{
				XYZ startPoint = list2[0].Segment.StartPoint;
				if (Geometry.IsEqual(startPoint, newSegment.Segment.EndPoint, 0.0001))
				{
					flag2 = true;
				}
			}
			else
			{
				flag2 = true;
			}
			if (!flag && !flag2)
			{
				newSegment.Segment.ReverseSelf();
				return;
			}
			if (!flag)
			{
				if (list.Count > list2.Count + 1)
				{
					list2.Add(newSegment);
					using (List<BaseLineSegment>.Enumerator enumerator = list2.GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							BaseLineSegment baseLineSegment = enumerator.Current;
							baseLineSegment.Segment.ReverseSelf();
						}
						return;
					}
				}
				using (List<BaseLineSegment>.Enumerator enumerator2 = list.GetEnumerator())
				{
					while (enumerator2.MoveNext())
					{
						BaseLineSegment baseLineSegment2 = enumerator2.Current;
						baseLineSegment2.Segment.ReverseSelf();
					}
					return;
				}
			}
			if (!flag2)
			{
				if (list2.Count > list.Count + 1)
				{
					list.Add(newSegment);
					using (List<BaseLineSegment>.Enumerator enumerator3 = list.GetEnumerator())
					{
						while (enumerator3.MoveNext())
						{
							BaseLineSegment baseLineSegment3 = enumerator3.Current;
							baseLineSegment3.Segment.ReverseSelf();
						}
						return;
					}
				}
				foreach (BaseLineSegment baseLineSegment4 in list2)
				{
					baseLineSegment4.Segment.ReverseSelf();
				}
			}
		}

		private List<BaseLineNode> GetAllNodes()
		{
			List<BaseLineNode> list = new List<BaseLineNode>();
			foreach (KeyValuePair<XYZ, BaseLineNode> keyValuePair in this.m_LinkedGraph)
			{
				list.Add(keyValuePair.Value);
			}
			return list;
		}

		private BaseLineNode GetLeftBottomNode(List<BaseLineNode> theNodes)
		{
			XYZ xyz = theNodes[0].Position;
			BaseLineNode result = null;
			foreach (BaseLineNode baseLineNode in theNodes)
			{
				XYZ position = baseLineNode.Position;
				if (Geometry.IsEqual(position, xyz, 0.0001))
				{
					result = baseLineNode;
				}
				else if (this.CompareXYLess(position, xyz))
				{
					xyz = position;
					result = baseLineNode;
				}
			}
			return result;
		}

		private bool CompareXYLess(XYZ lhv, XYZ rhv)
		{
			if (Geometry.IsEqual(lhv.Y, rhv.Y))
			{
				if (Geometry.LessThan(lhv.X, rhv.X))
				{
					return true;
				}
			}
			else if (Geometry.LessThan(lhv.Y, rhv.Y))
			{
				return true;
			}
			return false;
		}

		private bool GetLinkedBaseLineSegments(BaseLineSegment segment, ref List<BaseLineSegment> startlinkedSegments, ref List<BaseLineSegment> endlinkedSegments, ref List<BaseLineNode> passedNodes)
		{
			List<BaseLineNode> allNodes = this.GetAllNodes();
			XYZ startPoint = segment.Segment.StartPoint;
			XYZ endPoint = segment.Segment.EndPoint;
			BaseLineNode baseLineNode = null;
			BaseLineNode baseLineNode2 = null;
			if (this.m_LinkedGraph.ContainsKey(startPoint))
			{
				baseLineNode = this.m_LinkedGraph[startPoint];
			}
			if (this.m_LinkedGraph.ContainsKey(endPoint))
			{
				baseLineNode2 = this.m_LinkedGraph[endPoint];
			}
			if (baseLineNode == null || baseLineNode2 == null)
			{
				return false;
			}
			passedNodes.Add(baseLineNode);
			List<BaseLineSegment> list = new List<BaseLineSegment>();
			BaseLineSegmentLinkedGraph.FindNodeResult findNodeResult = this.FindLinkedSegments(endPoint, baseLineNode2, baseLineNode, allNodes, ref list, ref passedNodes);
			list.Reverse();
			startlinkedSegments.AddRange(list);
			passedNodes.Reverse();
			if (findNodeResult == BaseLineSegmentLinkedGraph.FindNodeResult.FR_Closed)
			{
				return true;
			}
			passedNodes.Add(baseLineNode2);
			this.FindLinkedSegments(startPoint, baseLineNode, baseLineNode2, allNodes, ref endlinkedSegments, ref passedNodes);
			return true;
		}

		private BaseLineSegmentLinkedGraph.FindNodeResult FindLinkedSegments(XYZ ptStart, BaseLineNode PrevNode, BaseLineNode CurNode, List<BaseLineNode> theNodes, ref List<BaseLineSegment> linkedSegments, ref List<BaseLineNode> passedNodes)
		{
			BaseLineSegment item = null;
			BaseLineNode nextNode = this.GetNextNode(PrevNode, CurNode, theNodes, ref item);
			if (nextNode == null || Geometry.IsEqual(nextNode.Position, PrevNode.Position, 0.0001))
			{
				return BaseLineSegmentLinkedGraph.FindNodeResult.FR_UnClosed;
			}
			passedNodes.Add(nextNode);
			linkedSegments.Add(item);
			if (Geometry.IsEqual(nextNode.Position, ptStart, 0.0001))
			{
				return BaseLineSegmentLinkedGraph.FindNodeResult.FR_Closed;
			}
			return this.FindLinkedSegments(ptStart, CurNode, nextNode, theNodes, ref linkedSegments, ref passedNodes);
		}

		private BaseLineNode GetNextNode(BaseLineNode PrevNode, BaseLineNode CurNode, List<BaseLineNode> theNodes, ref BaseLineSegment nextSegment)
		{
			BaseLineNode result = null;
			int num = CurNode.FindLinkSegmentWithOtherNode(PrevNode.Position);
			if (num != -1)
			{
				num++;
				if (num == CurNode.SegmentList.Count)
				{
					num = 0;
				}
				nextSegment = CurNode.SegmentList[num];
				XYZ pos = nextSegment.CurEndPoint(CurNode.Position);
				result = this.FindNodeByPos(theNodes, pos);
			}
			return result;
		}

		private BaseLineNode FindNodeByPos(List<BaseLineNode> theNodes, XYZ pos)
		{
			int num = theNodes.FindIndex((BaseLineNode value) => Geometry.IsEqual(pos, value.Position, 0.0001));
			if (num != -1)
			{
				return theNodes[num];
			}
			return null;
		}

		private Dictionary<XYZ, BaseLineNode> m_LinkedGraph = new Dictionary<XYZ, BaseLineNode>(new BaseLineSegmentLinkedGraph.XYZComparer());

		private class XYZComparer : IEqualityComparer<XYZ>
		{
			public bool Equals(XYZ p, XYZ q)
			{
				return Geometry.IsEqual(p, q, 0.0001);
			}

			public int GetHashCode(XYZ p)
			{
				string text = p.X.ToString("#0.00000");
				string text2 = p.Y.ToString("#0.00000");
				string text3 = p.Z.ToString("#0.00000");
				string text4 = string.Concat(new string[]
				{
					"(",
					text,
					",",
					text2,
					",",
					text3,
					")"
				});
				return text4.GetHashCode();
			}
		}

		private enum FindNodeResult
		{
			FR_UnClosed,
			FR_Closed
		}
	}
}
